//
// Created by Administrator on 2023/11/18.
//
#include "iostream"
#include <algorithm>

using namespace std;

const int N = 1e5 + 10, E = 2 * N;
int n, m;

struct Edge {
    int from;
    int to;
    int w;

    bool operator<(const Edge &t) const {
        return w < t.w;
    }
} edge[E];

int p[N];//并查集 判断连通性

int find(int x)//路径压缩的查询
{
    if (p[x] != x) p[x] = find(p[x]);
    else return x;
}

void kruskal() {
    //对边直接排序
    sort(edge, edge + m);

    int res = 0, cnt = 0;

    for (int i = 0; i < m; ++i) {
        auto t = edge[i];
        int a = t.from, b = t.to, w = t.w;
        //边是排好序的，直接从小到大进行选取，要注意的是得不在同一个并查集中，即不是同一联通分量
        a = find(a), b = find(b);//找根节点
        if (a != b) {
            res += w;
            cnt++;
            p[a] = b;//将a连到b上
        }
    }

    if (cnt != n - 1)cout << "impossible";
    else cout << res;

}

int main() {
    cin >> n >> m;

    //初始化并查集
    for (int i = 0; i < n; ++i) {
        p[i] = i;
    }
    for (int i = 0; i < m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        edge[i] = {u, v, w};
    }

    kruskal();
}